extends CharacterBody3D

class_name 玩家节点

@onready var 玩家相机: Camera3D = $"第一人称武器与相机/第一人称相机"
@onready var 第一人称武器与相机: Node3D = $"第一人称武器与相机"
@onready var 输入操作控制节点: Node = $"输入操作控制节点"


@onready var 上楼梯判定点 = abs($"楼梯攀登点".position.z)

##移动速度标准为10，之后可能会更改。
@export var 移动速度:float = 10.0
##玩家跳跃时施加的向上的力，在跳跃时依旧会受到重力的影响。
@export var 跳跃高度:float = 8.0
##玩家当前受到的重力的倍率，调整这个可以使玩家可跳跃高度与下落速度产生变化，默认为2.0。
@export var 重力倍率:float = 2.0
##当玩家与物理体碰撞时，物理体可以被推动，力量指的是可以推动的物理体的重量上限。
@export var 力量:float = 8.0
##可以调整玩家的可视角度，也可以作为武器瞄具缩放的设置。
@export_range(60.0,130.0) var FOV设置:float = 75.0



var 当前fov:float = FOV设置


var 重力: float = ProjectSettings.get_setting("physics/3d/default_gravity")
var 相机转向角度 = Vector2(0,0)


func _ready() -> void:
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	玩家相机.fov = FOV设置
	当前移动速度 = 移动速度


var 视角渐变:Vector2
func 相机看向(视角移动:Vector2):
	相机转向角度 += 视角移动
	相机转向角度.y = clamp(相机转向角度.y,-1.5,1.5)
	transform.basis =Basis()
	玩家相机.transform.basis = Basis()
	rotate_object_local(Vector3(0,1,0), -相机转向角度.x)
	玩家相机.rotate_object_local(Vector3(1,0,0), -相机转向角度.y)
	视角渐变 = 视角移动


func 上楼梯():
	var 判定点方位 = velocity * Vector3(1,0,1)  
	var 判定方位 = 判定点方位.normalized() * 上楼梯判定点
	$"楼梯攀登点".global_position.x = self.global_position.x + 判定方位.x
	$"楼梯攀登点".global_position.z = self.global_position.z + 判定方位.z


var 最后一帧是否在地板上 = false
var 是否在第一帧捕获楼梯 = false
func 下楼梯():
	var 是否捕获 = false
	if not is_on_floor() and velocity.y <= 0 and (最后一帧是否在地板上 or 是否在第一帧捕获楼梯) :
		var 玩家物理 = PhysicsTestMotionResult3D.new()
		var 运动参数 =PhysicsTestMotionParameters3D.new()
		var 最大下楼梯幅度 = -0.5
		运动参数.from = self.global_transform
		运动参数.motion = Vector3(0,最大下楼梯幅度,0)
		if PhysicsServer3D.body_test_motion(self.get_rid(),运动参数,玩家物理):
			var y轴变动 = 玩家物理.get_travel().y
			self.position.y += y轴变动
			apply_floor_snap()
			是否捕获 = true
	最后一帧是否在地板上 =  is_on_floor()
	是否在第一帧捕获楼梯 = 是否捕获


var 当前移动速度:float 
var 移动向量 :Vector3
var 移动速率:float 
func 移动控制(移动方向:Vector2,delta: float) -> void:
	if not is_on_floor():
		velocity.y -= ( 重力 * 重力倍率 ) * delta
	#限制手柄输入最大值.
	if (abs(移动方向.x)+abs(移动方向.y)) > 1:
		移动速率 =  1 
	else :
		移动速率 = (abs(移动方向.x)+abs(移动方向.y))
	#移动向量在状态机里使用
	移动向量 = (transform.basis * Vector3(移动方向.x, 0, 移动方向.y)).normalized()
	#防止玩家利用上楼梯的功能翻墙的东西
	if not is_on_floor():
		$"楼梯攀登点".disabled=true
	else :
		$"楼梯攀登点".disabled=false
	上楼梯()
	move_and_slide()
	下楼梯()
	武器动态运动(移动方向.x,abs(移动方向.x) + abs(移动方向.y),delta)
	碰撞体推动检测()


func 碰撞体推动检测():
	#在接触世界物理体时，推动物理体。
	for i in get_slide_collision_count():
		var c = get_slide_collision(i)
		if c.get_collider() is RigidBody3D:
			c.get_collider().apply_central_impulse(-c.get_normal() * 力量)


func 武器动态运动(偏转角度,移动数值,delta):
	相机视角偏转(偏转角度,delta)
	$"第一人称武器与相机/第一人称相机/武器状态机".武器动态偏转(偏转角度,delta)
	$"第一人称武器与相机/第一人称相机/武器状态机".武器动态视角(视角渐变,delta)
	$"第一人称武器与相机/第一人称相机/武器状态机".武器移动摆动(移动数值,delta)



func 相机视角偏转(偏转方向:float,事件时间:float):
	var 角度 = $"第一人称武器与相机".rotation_degrees.z
	$"第一人称武器与相机".rotation_degrees.z = lerp(角度,-偏转方向,10*事件时间)
